package service

import (
	"astgram/common"
	"astgram/dal/po"
	"astgram/dal/repo"
	"astgram/model"
	"context"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/spf13/cast"
	"hash/fnv"
	"math/rand"
	"mime/multipart"
	"path/filepath"
	"time"
)

type UploadImageService struct {
}

func (ss *UploadImageService) checkParam(file *multipart.FileHeader) error {
	// 校验图片类型
	if !common.IsImage(file.Filename) {
		return errors.New("未知的图片类型")
	}
	return nil
}

func (ss *UploadImageService) Execute(c *gin.Context) (*model.UploadImageResponse, error) {
	file, err := c.FormFile("file")
	if err != nil {
		return nil, err
	}
	if err = ss.checkParam(file); err != nil {
		return nil, err
	}
	key := ss.GenerateObjKey(c, file.Filename)
	if err = ss.UploadImage(c, key, file); err != nil {
		return nil, err
	}

	imageRepo := repo.NewImageRepo()
	user := common.GetUser(c)
	err = imageRepo.CreateImage(&po.Image{
		UserID: user.UserID,
		URL:    common.GetUrl(key),
	})
	if err != nil {
		return nil, err
	}

	return &model.UploadImageResponse{
		Meta:     common.MetaOk,
		ImageURL: common.GetUrl(key),
	}, nil
}

func (ss *UploadImageService) UploadImage(ctx context.Context, key string, file *multipart.FileHeader) error {
	fileHandle, err := file.Open() //打开上传文件
	if err != nil {
		return err
	}
	defer fileHandle.Close()
	return common.UploadFile(ctx, key, fileHandle)
}

func hash(s string) uint32 {
	h := fnv.New32a()
	h.Write([]byte(s))
	return h.Sum32()
}

func (ss *UploadImageService) GenerateObjKey(ctx context.Context, filename string) string {
	ext := filepath.Ext(filename)
	user := common.GetUser(ctx)
	dir := fmt.Sprintf("images/%s", time.Now().Format("200601"))
	u := hash(cast.ToString(user.UserID))
	t := time.Now().Unix()
	r := rand.Intn(100)
	return fmt.Sprintf("%s/%d_%d_%d%s", dir, u, t, r, ext)
}
